﻿using System;
using System.Text;
// C#的类型转换运算符可以进行多种转换，包括：
//    数值型转换
//    引用型转换
//    装箱/拆箱转换
//    自定义转换（通过运算符重载）
namespace _074_类型参数的转换
{
    class Program
    {
        // 根据原数据的类型，在编译时决定转换成何种类型，并实现转换。因为编译时还不知道原数据的确切类型，使得泛型参数具有有趣的语义。如果导致二义性，编译器会产生一个错误。
        //最常见的应用是实现一个引用的类型转换：
        /*StringBuilder Foo<T> (T arg)
        {
            if (arg is StringBuilder)
                return (StringBuilder)arg; // 编译不通过
            return default;
        }*/
        // 因为不知道T的确切类型，编译器认为是自定义转换。
        // 最简单的解决方法就是改用as运算符，因为它不能进行自定义类型转换，所以不会产生二义性。
        StringBuilder Foo<T> (T arg)
        {
            StringBuilder sb = arg as StringBuilder;
            if (sb != null) return sb;
            return default;
        }
        // 一般的做法是，先转换成object类型。这种方法能够实现，是因为转换自或转换到object类型，被假定为不是自定义转换而是引用或装箱/拆箱转换。
        //下例中，StringBuilder是引用类型，所以必须引用转换：
        //return (StringBuilder)(object) arg;

        // 拆箱转换也会产生二义性。
        //下面可能是拆箱转换、数值转换或自定义转换：
        //int Foo1<T>(T x) { return (int)x; } // 编译时错误
        //下面的方法先转换成object再转换成int（很明显这是一个拆箱转换）：
        int Foo1<T>(T x) { return (int)(object)x; }
        static void Main(string[] args)
        {
        }
    }
}
